#include "Logger.h"
#include "filesystem"
#include <iostream>
#include <fstream>
#include <cstdarg>
#include <sys/syscall.h>
#include <unistd.h>
#include "Config.h"

Logger::Logger()
{
    SetFileDir(Config::GetInstance().GetValue("log_path"));
    Start();
}

Logger::~Logger()
{
}

Logger &Logger::GetInstance()
{
    static Logger logger;
    return logger;
}

void Logger::SetFileDir(const std::string &file_dir)
{
    m_file_dir = file_dir;
}

void Logger::AddToQueue(const char *level, const char *file, int line, const char *func, const std::string &format,
                        ...)
{
    va_list args;
    va_start(args, format);
    char msg[1024] = {0};
    vsnprintf(msg, sizeof(msg), format.c_str(), args);

    //[2024-12-19 14:35:58][INFO][4614][TcpServer.hpp:48 void TcpServer::InitServer()] TcpServer Init Success
    time_t now = time(nullptr);
    struct tm *tm_now = localtime(&now);
    char log[2048] = {0};
    sprintf(log, "[%04d-%02d-%02d %02d:%02d:%02d][%s][%ld][%s:%d %s] %s\n",
            tm_now->tm_year + 1900,
            tm_now->tm_mon + 1,
            tm_now->tm_mday,
            tm_now->tm_hour,
            tm_now->tm_min,
            tm_now->tm_sec,
            level,
            syscall(SYS_gettid),
            file,
            line,
            func,
            msg);

    m_log_queue.push(log);
}

void Logger::Start()
{
    // 创建写日志线程
    std::thread write_log_thread(&Logger::WriteLog, this);
    // 设置线程分离
    write_log_thread.detach();
}

void Logger::WriteLog()
{
    while (true)
    {
        // 如果有m_file_dir,判断目录是否存在，没有则创建
        if (!m_file_dir.empty())
        {
            if (!std::filesystem::exists(m_file_dir))
            {
                if (!std::filesystem::create_directories(m_file_dir))
                {
                    std::cerr << "create log directory failed" << std::endl;
                    return;
                }
            }
        }

        // 拼接字符串，获得日志文件路径
        time_t now = time(nullptr);
        tm *tm_now = localtime(&now);
        char filename[100] = {0};
        sprintf(filename, "%04d%02d%02d.log",
                tm_now->tm_year + 1900,
                tm_now->tm_mon + 1,
                tm_now->tm_mday);
        std::string log_path = m_file_dir + filename;

        // 打开日志文件，写入日志
        std::fstream outfile(log_path, std::ios::out | std::ios::app);
        if (!outfile.is_open())
        {
            std::cerr << "open log file failed" << std::endl;
            return;
        }
        std::string log = m_log_queue.pop();
        outfile << log;

        // 关闭日志文件
        outfile.flush();
        outfile.close();
    }
}
